package com.jfs.zlk.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson2.JSON;
import com.jfs.constant.CommonConstant;
import com.jfs.zlk.config.ZlkMediaServerInfo;
import com.jfs.zlk.entity.StreamInfo;
import com.jfs.zlk.entity.ZlkResult;
import com.jfs.zlk.entity.request.BaseRequest;
import com.jfs.zlk.entity.request.IsMediaOnline;
import com.jfs.zlk.entity.request.RequestOpenRtpServer;
import com.jfs.zlk.entity.request.RequestSetServerConfig;
import com.jfs.zlk.entity.response.ResponseIsMediaOnline;
import com.jfs.zlk.entity.response.ResponseOpenRtpServer;
import com.jfs.zlk.entity.response.ResponseSetServerConfig;
import com.jfs.zlk.enums.MediaServerEnum;
import com.jfs.zlk.enums.ZlkResultCode;
import com.jfs.zlk.properties.ZlkMediaServerProperties;
import com.jfs.zlk.service.ZlkMediaServerService;
import com.jfs.zlk.util.HttpUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.Objects;

/**
 * @Description 流媒体服务接口实现类
 * @E-mail cwm3412638@163.com
 * @Author cwm
 * @Date 2022/7/27
 */
@Service
@AllArgsConstructor
@Slf4j
public class ZlkMediaServerServiceImpl implements ZlkMediaServerService {
    private final ZlkMediaServerProperties zlkMediaServerProperties;
    private final RestTemplate restTemplate;

    @Override
    public ZlkMediaServerInfo getServerConfig() {
        try {
            String url = CommonConstant.HTTP_PREFIX + zlkMediaServerProperties.getIpAddress() + CommonConstant.COLON + zlkMediaServerProperties.getPort() + MediaServerEnum.GET_SERVER_CONFIG.getUrl();
            url = HttpUtils.initUriPathParams(url, new BaseRequest(zlkMediaServerProperties.getSecret()), BaseRequest.class);
            ResponseEntity<ZlkResult> responseEntity = this.restTemplate.getForEntity(url, ZlkResult.class);
            //判断http 响应状态
            if (responseEntity.getStatusCode().equals(HttpStatus.OK)) {
                ZlkResult<JSONArray> zlkResult = responseEntity.getBody();
                if (ZlkResultCode.SUCCESS.getCode().equals(zlkResult.getCode())) {
                    JSONArray data = zlkResult.getData();
                    if (log.isDebugEnabled()) {
                        log.debug("获取zlk流媒体服务器配置成功！！！");
                    }
                    return JSON.to( ZlkMediaServerInfo.class,data.get(0));
                } else {
                    log.error("获取服务器配置失败,code:{},msg:{}", zlkResult.getCode(), zlkResult.getMsg());
                }
            }
        } catch (Exception e) {
            log.error("获取服务器配置失败:{}", e.getMessage());
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public ResponseOpenRtpServer openRtpServer(RequestOpenRtpServer requestOpenRtpServer) {
        try {
            String url = CommonConstant.HTTP_PREFIX + zlkMediaServerProperties.getIpAddress() + CommonConstant.COLON + zlkMediaServerProperties.getPort() + MediaServerEnum.OPEN_RTP_SERVER.getUrl();
            url = HttpUtils.initUriPathParams(url, requestOpenRtpServer, RequestOpenRtpServer.class);
            ResponseEntity<ResponseOpenRtpServer> responseEntity = this.restTemplate.getForEntity(url, ResponseOpenRtpServer.class);
            //判断http 响应状态
            if (responseEntity.getStatusCode().equals(HttpStatus.OK)) {
                if (log.isDebugEnabled()) {
                    log.debug("创建GB28181 RTP接收端口成功");
                }
                return responseEntity.getBody();
            }
        } catch (Exception e) {
            log.error("创建GB28181 RTP接收端口失败:{}", e.getMessage());
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public ResponseSetServerConfig setServerConfig(RequestSetServerConfig requestSetServerConfig) {
        try {
            String url = CommonConstant.HTTP_PREFIX + zlkMediaServerProperties.getIpAddress() + CommonConstant.COLON + zlkMediaServerProperties.getPort() + MediaServerEnum.SET_SERVER_CONFIG.getUrl();
            url = HttpUtils.initUriPathParams(url, new BaseRequest(zlkMediaServerProperties.getSecret()), BaseRequest.class);
            HttpEntity<String> httpEntity = new HttpEntity<>(JSON.toJSONString(requestSetServerConfig), null);
            ResponseEntity<ResponseSetServerConfig> responseEntity = this.restTemplate.exchange(url, HttpMethod.POST, httpEntity, ResponseSetServerConfig.class);
            //判断http 响应状态
            if (responseEntity.getStatusCode().equals(HttpStatus.OK)) {
                if (ZlkResultCode.SUCCESS.getCode().equals(Objects.requireNonNull(responseEntity.getBody()).getCode())) {
                    if (log.isDebugEnabled()) {
                        log.debug("设置服务器配置成功!!!");
                    }
                    return responseEntity.getBody();
                }
            }
        } catch (Exception e) {
            log.error("设置服务器配置发生异常:{}", e.getMessage());
        }
        return null;
    }

    @Override
    public StreamInfo getMedia(ZlkMediaServerInfo zlkMediaServerInfo, String appId, String streamId) {
        StreamInfo streamInfoResult = new StreamInfo();
        streamInfoResult.setStream(streamId);
        streamInfoResult.setApp(appId);
        streamInfoResult.setRtmp(String.format("rtmp://%s:%s/%s/%s", zlkMediaServerProperties.getIpAddress(), zlkMediaServerInfo.getRtmpPort(), appId, streamId));
        if (!"0".equals(zlkMediaServerInfo.getRtmpSslport())) {
            streamInfoResult.setRtmps(String.format("rtmps://%s:%s/%s/%s", zlkMediaServerProperties.getIpAddress(), zlkMediaServerInfo.getRtmpSslport(), appId, streamId));
        }
        streamInfoResult.setRtsp(String.format("rtsp://%s:%s/%s/%s", zlkMediaServerProperties.getIpAddress(), zlkMediaServerInfo.getRtspPort(), appId, streamId));
        if (!"0".equals(zlkMediaServerInfo.getRtspSslport())) {
            streamInfoResult.setRtsps(String.format("rtsps://%s:%s/%s/%s", zlkMediaServerProperties.getIpAddress(), zlkMediaServerInfo.getRtspSslport(), appId, streamId));
        }
        streamInfoResult.setFlv(String.format("http://%s:%s/%s/%s.live.flv", zlkMediaServerProperties.getIpAddress(), zlkMediaServerInfo.getHttpPort(), appId, streamId));
        streamInfoResult.setWsFlv(String.format("ws://%s:%s/%s/%s.live.flv", zlkMediaServerProperties.getIpAddress(), zlkMediaServerInfo.getHttpPort(), appId, streamId));
        streamInfoResult.setHls(String.format("http://%s:%s/%s/%s/hls.m3u8", zlkMediaServerProperties.getIpAddress(), zlkMediaServerInfo.getHttpPort(), appId, streamId));
        streamInfoResult.setWsHls(String.format("ws://%s:%s/%s/%s/hls.m3u8", zlkMediaServerProperties.getIpAddress(), zlkMediaServerInfo.getHttpPort(), appId, streamId));
        streamInfoResult.setFmp4(String.format("http://%s:%s/%s/%s.live.mp4", zlkMediaServerProperties.getIpAddress(), zlkMediaServerInfo.getHttpPort(), appId, streamId));
        streamInfoResult.setWsFmp4(String.format("ws://%s:%s/%s/%s.live.mp4", zlkMediaServerProperties.getIpAddress(), zlkMediaServerInfo.getHttpPort(), appId, streamId));
        streamInfoResult.setTs(String.format("http://%s:%s/%s/%s.live.ts", zlkMediaServerProperties.getIpAddress(), zlkMediaServerInfo.getHttpPort(), appId, streamId));
        streamInfoResult.setWsTs(String.format("ws://%s:%s/%s/%s.live.ts", zlkMediaServerProperties.getIpAddress(), zlkMediaServerInfo.getHttpPort(), appId, streamId));
        if (!"0".equals(zlkMediaServerInfo.getHttpSSLport())) {
            streamInfoResult.setHttpsFlv(String.format("https://%s:%s/%s/%s.live.flv", zlkMediaServerProperties.getIpAddress(), zlkMediaServerInfo.getHttpSSLport(), appId, streamId));
            streamInfoResult.setWssFlv(String.format("wss://%s:%s/%s/%s.live.flv", zlkMediaServerProperties.getIpAddress(), zlkMediaServerInfo.getHttpSSLport(), appId, streamId));
            streamInfoResult.setHttpsHls(String.format("https://%s:%s/%s/%s/hls.m3u8", zlkMediaServerProperties.getIpAddress(), zlkMediaServerInfo.getHttpSSLport(), appId, streamId));
            streamInfoResult.setWssHls(String.format("wss://%s:%s/%s/%s/hls.m3u8", zlkMediaServerProperties.getIpAddress(), zlkMediaServerInfo.getHttpSSLport(), appId, streamId));
            streamInfoResult.setHttpsFmp4(String.format("https://%s:%s/%s/%s.live.mp4", zlkMediaServerProperties.getIpAddress(), zlkMediaServerInfo.getHttpSSLport(), appId, streamId));
            streamInfoResult.setWssFmp4(String.format("wss://%s:%s/%s/%s.live.mp4", zlkMediaServerProperties.getIpAddress(), zlkMediaServerInfo.getHttpSSLport(), appId, streamId));
            streamInfoResult.setHttpsTs(String.format("https://%s:%s/%s/%s.live.ts", zlkMediaServerProperties.getIpAddress(), zlkMediaServerInfo.getHttpSSLport(), appId, streamId));
            streamInfoResult.setWssTs(String.format("wss://%s:%s/%s/%s.live.ts", zlkMediaServerProperties.getIpAddress(), zlkMediaServerInfo.getHttpSSLport(), appId, streamId));
            streamInfoResult.setWssTs(String.format("wss://%s:%s/%s/%s.live.ts", zlkMediaServerProperties.getIpAddress(), zlkMediaServerInfo.getHttpSSLport(), appId, streamId));
        }
        return streamInfoResult;
    }

    @Override
    public Boolean isMediaOnline(IsMediaOnline isMediaOnline) {
        try {
            String url = CommonConstant.HTTP_PREFIX + zlkMediaServerProperties.getIpAddress() + CommonConstant.COLON + zlkMediaServerProperties.getPort() + MediaServerEnum.IS_MEDIA_ONLINE.getUrl();
            url = HttpUtils.initUriPathParams(url, isMediaOnline, IsMediaOnline.class);
            ResponseEntity<ResponseIsMediaOnline> responseEntity = this.restTemplate.getForEntity(url, ResponseIsMediaOnline.class);
            if (responseEntity.getStatusCode().equals(HttpStatus.OK)){
                if (ZlkResultCode.SUCCESS.getCode().equals(Objects.requireNonNull(responseEntity.getBody()).getCode())
                        && Objects.nonNull(responseEntity.getBody().getData())
                ){
                    return true;
                }
            }
        }catch (Exception e){
            log.error("判断直播流是否在线发生异常:{}", e.getMessage());
            return false;
        }
        return false;
    }

}
